home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / mg2a_src.zip / SEARCH.C < prev    next >
C/C++ Source or Header  |  1991-03-10  |  15KB  |  669 lines

  1. /*
  2.  *        Search commands.
  3.  * The functions in this file implement the
  4.  * search commands (both plain and incremental searches
  5.  * are supported) and the query-replace command.
  6.  *
  7.  * The plain old search code is part of the original
  8.  * MicroEMACS "distribution". The incremental search code,
  9.  * and the query-replace code, is by Rich Ellison.
  10.  */
  11. #include    "def.h"
  12. #ifndef NO_MACRO
  13. #include    "macro.h"
  14. #endif
  15.  
  16. #define SRCH_BEGIN    (0)            /* Search sub-codes.    */
  17. #define SRCH_FORW    (-1)
  18. #define SRCH_BACK    (-2)
  19. #define SRCH_NOPR    (-3)
  20. #define SRCH_ACCM    (-4)
  21. #define SRCH_MARK    (-5)
  22.  
  23. typedef struct    {
  24.     int    s_code;
  25.     LINE    *s_dotp;
  26.     int    s_doto;
  27. }    SRCHCOM;
  28.  
  29. static    SRCHCOM cmds[NSRCH];
  30. static    int    cip;
  31.  
  32. int    srch_lastdir = SRCH_NOPR;        /* Last search flags.    */
  33.  
  34. static VOID    is_cpush();
  35. static VOID    is_lpush();
  36. static VOID    is_pop();
  37. static int    is_peek();
  38. static VOID    is_undo();
  39. static int    is_find();
  40. static VOID    is_prompt();
  41. static VOID    is_dspl();
  42. static int    eq();
  43.  
  44. /*
  45.  * Search forward.
  46.  * Get a search string from the user, and search for it,
  47.  * starting at ".". If found, "." gets moved to just after the
  48.  * matched characters, and display does all the hard stuff.
  49.  * If not found, it just prints a message.
  50.  */
  51. /*ARGSUSED*/
  52. forwsearch(f, n)
  53. {
  54.     register int    s;
  55.  
  56.     if ((s=readpattern("Search")) != TRUE)
  57.         return s;
  58.     if (forwsrch() == FALSE) {
  59.         ewprintf("Search failed: \"%s\"", pat);
  60.         return FALSE;
  61.     }
  62.     srch_lastdir = SRCH_FORW;
  63.     return TRUE;
  64. }
  65.  
  66. /*
  67.  * Reverse search.
  68.  * Get a search string from the     user, and search, starting at "."
  69.  * and proceeding toward the front of the buffer. If found "." is left
  70.  * pointing at the first character of the pattern [the last character that
  71.  * was matched].
  72.  */
  73. /*ARGSUSED*/
  74. backsearch(f, n)
  75. {
  76.     register int    s;
  77.  
  78.     if ((s=readpattern("Search backward")) != TRUE)
  79.         return (s);
  80.     if (backsrch() == FALSE) {
  81.         ewprintf("Search failed: \"%s\"", pat);
  82.         return FALSE;
  83.     }
  84.     srch_lastdir = SRCH_BACK;
  85.     return TRUE;
  86. }
  87.  
  88. /*
  89.  * Search again, using the same search string
  90.  * and direction as the last search command. The direction
  91.  * has been saved in "srch_lastdir", so you know which way
  92.  * to go.
  93.  */
  94. /*ARGSUSED*/
  95. searchagain(f, n)
  96. {
  97.     if (srch_lastdir == SRCH_FORW) {
  98.         if (forwsrch() == FALSE) {
  99.             ewprintf("Search failed: \"%s\"", pat);
  100.             return FALSE;
  101.         }
  102.         return TRUE;
  103.     }
  104.     if (srch_lastdir == SRCH_BACK) {
  105.         if (backsrch() == FALSE) {
  106.             ewprintf("Search failed: \"%s\"", pat);
  107.             return FALSE;
  108.         }
  109.         return TRUE;
  110.     }
  111.     ewprintf("No last search");
  112.     return FALSE;
  113. }
  114.  
  115. /*
  116.  * Use incremental searching, initially in the forward direction.
  117.  * isearch ignores any explicit arguments.
  118.  */
  119. /*ARGSUSED*/
  120. forwisearch(f, n)
  121. {
  122.     return isearch(SRCH_FORW);
  123. }
  124.  
  125. /*
  126.  * Use incremental searching, initially in the reverse direction.
  127.  * isearch ignores any explicit arguments.
  128.  */
  129. /*ARGSUSED*/
  130. backisearch(f, n)
  131. {
  132.     return isearch(SRCH_BACK);
  133. }
  134.  
  135. /*
  136.  * Incremental Search.
  137.  *    dir is used as the initial direction to search.
  138.  *    ^S    switch direction to forward
  139.  *    ^R    switch direction to reverse
  140.  *    ^Q    quote next character (allows searching for ^N etc.)
  141.  *    <ESC>    exit from Isearch
  142.  *    <DEL>    undoes last character typed. (tricky job to do this correctly).
  143.  *    other ^ exit search, don't set mark
  144.  *    else    accumulate into search string
  145.  */
  146. isearch(dir) {
  147.     register int    c;
  148.     register LINE    *clp;
  149.     register int    cbo;
  150.     register int    success;
  151.     int        pptr;
  152.     char        opat[NPAT];
  153.     VOID        ungetkey();
  154.  
  155. #ifndef NO_MACRO
  156.     if(macrodef) {
  157.         ewprintf("Can't isearch in macro");
  158.         return FALSE;
  159.     }
  160. #endif
  161.     for (cip=0; cip<NSRCH; cip++)
  162.         cmds[cip].s_code = SRCH_NOPR;
  163.     (VOID) strcpy(opat, pat);
  164.     cip = 0;
  165.     pptr = -1;
  166.     clp = curwp->w_dotp;
  167.     cbo = curwp->w_doto;
  168.     is_lpush();
  169.     is_cpush(SRCH_BEGIN);
  170.     success = TRUE;
  171.     is_prompt(dir, TRUE, success);
  172.     for (;;) {
  173.         update();
  174.         switch (c = getkey(FALSE)) {
  175.         case CCHR('['):
  176.             srch_lastdir = dir;
  177.             curwp->w_markp = clp;
  178.             curwp->w_marko = cbo;
  179.             ewprintf("Mark set");
  180.             return (TRUE);
  181.  
  182.         case CCHR('G'):
  183.             if (success != TRUE) {
  184.                 while (is_peek() == SRCH_ACCM)
  185.                     is_undo(&pptr, &dir);
  186.                 success = TRUE;
  187.                 is_prompt(dir, pptr < 0, success);
  188.                 break;
  189.             }
  190.             curwp->w_dotp = clp;
  191.             curwp->w_doto = cbo;
  192.             curwp->w_flag |= WFMOVE;
  193.             srch_lastdir = dir;
  194.             (VOID) ctrlg(FFRAND, 0);
  195.             (VOID) strcpy(pat, opat);
  196.             return ABORT;
  197.  
  198.         case CCHR(']'):
  199.         case CCHR('S'):
  200.             if (dir == SRCH_BACK) {
  201.                 dir = SRCH_FORW;
  202.                 is_lpush();
  203.                 is_cpush(SRCH_FORW);
  204.                 success = TRUE;
  205.             }
  206.             if (success==FALSE && dir==SRCH_FORW)
  207.                 break;
  208.             is_lpush();
  209.             pptr = strlen(pat);
  210.             (VOID) forwchar(FFRAND, 1);
  211.             if (is_find(SRCH_FORW) != FALSE) is_cpush(SRCH_MARK);
  212.             else {
  213.                 (VOID) backchar(FFRAND, 1);
  214.                 ttbeep();
  215.                 success = FALSE;
  216.             }
  217.             is_prompt(dir, pptr < 0, success);
  218.             break;
  219.  
  220.         case CCHR('R'):
  221.             if (dir == SRCH_FORW) {
  222.                 dir = SRCH_BACK;
  223.                 is_lpush();
  224.                 is_cpush(SRCH_BACK);
  225.                 success = TRUE;
  226.             }
  227.             if (success==FALSE && dir==SRCH_BACK)
  228.                 break;
  229.             is_lpush();
  230.             pptr = strlen(pat);
  231.             (VOID) backchar(FFRAND, 1);
  232.             if (is_find(SRCH_BACK) != FALSE) is_cpush(SRCH_MARK);
  233.             else {
  234.                 (VOID) forwchar(FFRAND, 1);
  235.                 ttbeep();
  236.                 success = FALSE;
  237.             }
  238.             is_prompt(dir, pptr < 0, success);
  239.             break;
  240.  
  241.         case CCHR('H'):
  242.         case CCHR('?'):
  243.             is_undo(&pptr, &dir);
  244.             if (is_peek() != SRCH_ACCM) success = TRUE;
  245.             is_prompt(dir, pptr < 0, success);
  246.             break;
  247.  
  248.         case CCHR('\\'):
  249.         case CCHR('Q'):
  250.             c = (char) getkey(FALSE);
  251.             goto  addchar;
  252.         case CCHR('M'):
  253.             c = CCHR('J');
  254.             goto  addchar;
  255.  
  256.         default:
  257.             if (ISCTRL(c)) {
  258.                 ungetkey(c);
  259.                 curwp->w_markp = clp;
  260.                 curwp->w_marko = cbo;
  261.                 ewprintf("Mark set");
  262.                 curwp->w_flag |= WFMOVE;
  263.                 return    TRUE;
  264.             }    /* and continue */
  265.         case CCHR('I'):
  266.         case CCHR('J'):
  267.         addchar:
  268.             if (pptr == -1)
  269.                 pptr = 0;
  270.             if (pptr == 0)
  271.                 success = TRUE;
  272.             pat[pptr++] = c;
  273.             if (pptr == NPAT) {
  274.                 ewprintf("Pattern too long");
  275.                 return FALSE;
  276.             }
  277.             pat[pptr] = '\0';
  278.             is_lpush();
  279.             if (success != FALSE) {
  280.                 if (is_find(dir) != FALSE)
  281.                     is_cpush(c);
  282.                 else {
  283.                     success = FALSE;
  284.                     ttbeep();
  285.                     is_cpush(SRCH_ACCM);
  286.                 }
  287.             } else
  288.                 is_cpush(SRCH_ACCM);
  289.             is_prompt(dir, FALSE, success);
  290.         }
  291.     }
  292.     /*NOTREACHED*/
  293. }
  294.  
  295. static VOID
  296. is_cpush(cmd) register int cmd; {
  297.     if (++cip >= NSRCH)
  298.         cip = 0;
  299.     cmds[cip].s_code = cmd;
  300. }
  301.  
  302. static VOID
  303. is_lpush() {
  304.     register int    ctp;
  305.  
  306.     ctp = cip+1;
  307.     if (ctp >= NSRCH)
  308.         ctp = 0;
  309.     cmds[ctp].s_code = SRCH_NOPR;
  310.     cmds[ctp].s_doto = curwp->w_doto;
  311.     cmds[ctp].s_dotp = curwp->w_dotp;
  312. }
  313.  
  314. static VOID
  315. is_pop() {
  316.     if (cmds[cip].s_code != SRCH_NOPR) {
  317.         curwp->w_doto  = cmds[cip].s_doto;
  318.         curwp->w_dotp  = cmds[cip].s_dotp;
  319.         curwp->w_flag |= WFMOVE;
  320.         cmds[cip].s_code = SRCH_NOPR;
  321.     }
  322.     if (--cip <= 0)
  323.         cip = NSRCH-1;
  324. }
  325.  
  326. static int
  327. is_peek() {
  328.     return cmds[cip].s_code;
  329. }
  330.  
  331. /* this used to always return TRUE (the return value was checked) */
  332. static VOID
  333. is_undo(pptr, dir) register int *pptr; register int *dir; {
  334.     register int    redo = FALSE ;
  335.     switch (cmds[cip].s_code) {
  336.     case SRCH_BEGIN:
  337.     case SRCH_NOPR:
  338.         *pptr = -1;
  339.     case SRCH_MARK:
  340.         break;
  341.  
  342.     case SRCH_FORW:
  343.         *dir = SRCH_BACK;
  344.         redo = TRUE;
  345.         break;
  346.  
  347.     case SRCH_BACK:
  348.         *dir = SRCH_FORW;
  349.         redo = TRUE;
  350.         break;
  351.  
  352.     case SRCH_ACCM:
  353.     default:
  354.         *pptr -= 1;
  355.         if (*pptr < 0)
  356.             *pptr = 0;
  357.         pat[*pptr] = '\0';
  358.         break;
  359.     }
  360.     is_pop();
  361.     if (redo) is_undo(pptr, dir);
  362. }
  363.  
  364. static int
  365. is_find(dir) register int dir; {
  366.     register int    plen, odoto;
  367.     register LINE    *odotp ;
  368.  
  369.     odoto = curwp->w_doto;
  370.     odotp = curwp->w_dotp;
  371.     plen = strlen(pat);
  372.     if (plen != 0) {
  373.         if (dir==SRCH_FORW) {
  374.             (VOID) backchar(FFARG | FFRAND, plen);
  375.             if (forwsrch() == FALSE) {
  376.                 curwp->w_doto = odoto;
  377.                 curwp->w_dotp = odotp;
  378.                 return FALSE;
  379.             }
  380.             return TRUE;
  381.         }
  382.         if (dir==SRCH_BACK) {
  383.             (VOID) forwchar(FFARG | FFRAND, plen);
  384.             if (backsrch() == FALSE) {
  385.                 curwp->w_doto = odoto;
  386.                 curwp->w_dot